package biz

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/opentracing/opentracing-go"
	"go-graduation/bff/internal/pkg/output"
	"go-graduation/logger/jaeger"
	proto "go-graduation/pb/router"
	"golang.org/x/sync/errgroup"
	"google.golang.org/grpc"
	"net/http"
	"strconv"
	"time"
)

func NewArticle(conn *grpc.ClientConn) *Article {
	return &Article{
		conn: conn,
	}
}

type Article struct {
	conn *grpc.ClientConn
}

// GetOneArticleById 根据ID获取某篇文章信息
func (a *Article) GetOneArticleById(ctx *gin.Context) {

	var result proto.ArticleDetailResponse_Data

	// todo 使用errGroup
	gCtx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	group, errCtx := errgroup.WithContext(gCtx)
	defer cancel()

	// 获取文章详情
	group.Go(func() error {

		detail, err := a.getArticleDetail(ctx)
		if err != nil {
			return err
		}
		result.Detail = detail
		return nil
	})

	// 获取评论列表
	group.Go(func() error {
		commentList, err := a.getCommentListByArticleId(ctx)
		if err != nil {
			return err
		}

		for _, item := range commentList {
			result.Comment = append(result.Comment, &proto.ArticleDetailResponse_Comments{
				Id:      item.Id,
				Content: item.Content,
				UserId:  item.UserId,
			})
		}
		return nil
	})

	group.Go(func() error {
		for {
			select {
			case <-errCtx.Done(): // 错误退出
				return errCtx.Err()
			default:
				return nil
			}
		}
	})

	// 捕获err
	if err := group.Wait(); err != nil {
		// todo 写日志
		output.NewOutput().Failure(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	output.NewOutput().Success(ctx, result)
	return
}

// getArticleDetail 获取文章的详情
func (a *Article) getArticleDetail(ctx *gin.Context) (*proto.ArticleDetailResponse_Detail, error) {
	client := proto.NewArticleDetailServiceClient(a.conn)
	id, _ := strconv.Atoi(ctx.Query("id"))
	req := &proto.ArticleDetailRequest{
		Id: int64(id),
	}
	res, err := client.ArticleDetail(ctx, req)
	if err != nil {
		return nil, err
	}
	return res.Data.Detail, nil
}

// getCommentListByArticleId 获取文章的评论列表
func (a *Article) getCommentListByArticleId(ctx *gin.Context) ([]*proto.ArticleCommentListResponse_Lists, error) {
	client := proto.NewArticleCommentListServiceClient(a.conn)
	page, _ := strconv.Atoi(ctx.Query("page"))
	req := &proto.ArticleCommentListRequest{
		Page: int64(page),
	}
	res, err := client.ArticleCommentList(ctx, req)
	if err != nil {
		return nil, err
	}
	fmt.Println(res)
	return res.Data.List, nil
}

// GetArticleByPage 获取全部文章
func (a *Article) GetArticleByPage(ctx *gin.Context) {

	tracer, _ := ctx.Get("Tracer")
	parentSpanContext, _ := ctx.Get("ParentSpanContext")
	jaeger.ClientInterceptor(tracer.(opentracing.Tracer), parentSpanContext.(opentracing.SpanContext))

	client := proto.NewArticleListServiceClient(a.conn)
	page, _ := strconv.Atoi(ctx.Query("page"))
	req := &proto.ArticleListRequest{
		Page: int64(page),
	}
	res, err := client.ArticleList(ctx, req)
	if err != nil {
		output.NewOutput().Failure(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	output.NewOutput().Success(ctx, res.Data)
	return
}
